package com.divemotor.ventarepuestosinternet.dao.impl;

import java.io.Serializable;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.primefaces.model.SortOrder;
import org.springframework.stereotype.Repository;
import com.divemotor.ventarepuestosinternet.dao.RepuestoDAO;
import com.divemotor.ventarepuestosinternet.model.Imagen;
import com.divemotor.ventarepuestosinternet.model.ImagenRepuesto;
import com.divemotor.ventarepuestosinternet.model.Promocion;
import com.divemotor.ventarepuestosinternet.model.PromocionRepuesto;
import com.divemotor.ventarepuestosinternet.model.Repuesto;
import com.divemotor.ventarepuestosinternet.util.Constantes;


@SuppressWarnings("unchecked")
@Repository(value="repuestoDAO")
public class RepuestoDAOImpl extends GenericoDAOImpl< Repuesto, Integer> implements RepuestoDAO,Serializable {

	private static final long serialVersionUID = 3816665150990364653L;

	public RepuestoDAOImpl(){
		setClase(Repuesto.class);
	}
	
	@Override
	public List<Repuesto> buscarRepuestos(Repuesto repuesto){
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class);
				
		if(repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")){
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if(repuesto.getNombre() != null && !repuesto.getNombre().equals("")){
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		if(repuesto.getEstado() != null && !repuesto.getEstado().equals(Constantes.NO_SELECCIONADO.toString())){
			criteria.add(Restrictions.eq("estado", repuesto.getEstado()));
		} else {
			criteria.add(Restrictions.not(Restrictions.eq("estado", Constantes.ESTADO_ELIMINADO)));
		}

		return criteria.list();
	}

	@Override
	public List<Repuesto> buscarRepuestos(int inicio, int numeroResultadosPorPagina, 
			SortOrder orden, String columnaOrden, Repuesto repuesto) {
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(
				Repuesto.class, "repuesto");

		criteria.setProjection(Projections.distinct(Projections
				.projectionList()
				.add(Projections.property("idRepuesto"), "idRepuesto")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("nombre"), "nombre")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("estado"), "estado")
				.add(Projections.property("unidadMedida"), "unidadMedida")
		));
	
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		if (repuesto.getEstado() != null && !repuesto.getEstado().equals(Constantes.NO_SELECCIONADO.toString())) {
			criteria.add(Restrictions.eq("estado", repuesto.getEstado()));
		} else {
			criteria.add(Restrictions.not(Restrictions.eq("estado", Constantes.ESTADO_ELIMINADO)));
		}
		
		criteria.setFirstResult(inicio);
		criteria.setMaxResults(numeroResultadosPorPagina);
		
		if (!(columnaOrden == null)) {
			if (orden.toString().equals(Constantes.ORDEN_ASCENDENTE_PRIMEFACES)) {
				criteria.addOrder(Order.asc(columnaOrden.toString()));
			} else {
				criteria.addOrder(Order.desc(columnaOrden.toString()));
			}
		}else{
			criteria.addOrder(Order.asc("nombre"));			
		}
		criteria.setResultTransformer(Transformers.aliasToBean(Repuesto.class));
		
		return criteria.list();
	}

	@Override
	public Integer obtenerNumeroRepuestosBusqueda(Repuesto repuesto) {
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class);
		criteria.setProjection(Projections.count("idRepuesto"));
		
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		if (repuesto.getEstado() != null && !repuesto.getEstado().equals(Constantes.NO_SELECCIONADO.toString())) {
			criteria.add(Restrictions.eq("estado", repuesto.getEstado()));
		} else {
			criteria.add(Restrictions.not(Restrictions.eq("estado", Constantes.ESTADO_ELIMINADO)));
		}
		
		Number result = (Number) criteria.uniqueResult();
		return new Integer(result.intValue());
	}

	@Override
	public List<Repuesto> buscarRepuestosAsignablesPorImagen(int inicio, int numeroResultadosPorPagina,
			SortOrder orden, String columnaOrden, Repuesto repuesto, Imagen imagen) {
		
		Criteria criteriaIdsRepuestosNoAsignables = sessionFactory.getCurrentSession().createCriteria(ImagenRepuesto.class, "imagenRepuesto")
				.createAlias("imagenRepuesto.imagen", "imagen")
				.createAlias("imagenRepuesto.repuesto", "repuesto")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("repuesto.idRepuesto"))))
				.add(Restrictions.eq("imagen.idImagen", imagen.getIdImagen()))
				.add(Restrictions.not(Restrictions.eq("imagenRepuesto.estado", Constantes.ESTADO_ELIMINADO)));
				
		List<Integer> listaIdsRepuestosNoAsignables = criteriaIdsRepuestosNoAsignables.list();
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class);
		
		criteria.setProjection(Projections.distinct(Projections
				.projectionList()
				.add(Projections.property("idRepuesto"), "idRepuesto")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("nombre"), "nombre")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("estado"), "estado")
				.add(Projections.property("unidadMedida"), "unidadMedida")

		));
		
		if (listaIdsRepuestosNoAsignables != null && listaIdsRepuestosNoAsignables.size() > 0) {
			criteria.add(Restrictions.not(Restrictions.in("idRepuesto", listaIdsRepuestosNoAsignables)));
		}
		
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		criteria.add(Restrictions.eq("estado", Constantes.ESTADO_ACTIVO));
		
		criteria.setFirstResult(inicio);
		criteria.setMaxResults(numeroResultadosPorPagina);
		
		if (!(columnaOrden == null)) {
			if (orden.toString().equals(Constantes.ORDEN_ASCENDENTE_PRIMEFACES)) {
				criteria.addOrder(Order.asc(columnaOrden.toString()));
			} else {
				criteria.addOrder(Order.desc(columnaOrden.toString()));
			}
		}
		criteria.setResultTransformer(Transformers.aliasToBean(Repuesto.class));
		
		return criteria.list();
	}

	@Override
	public List<Repuesto> buscarRepuestosAsignablesPorPromocion(int inicio, int numeroResultadosPorPagina, 
			SortOrder orden, String columnaOrden, Repuesto repuesto, Promocion promocion) {
		
		Criteria criteriaIdsRepuestosNoAsignables = sessionFactory.getCurrentSession().createCriteria(PromocionRepuesto.class, "promocionRepuesto")
				.createAlias("promocionRepuesto.promocion", "promocion")
				.createAlias("promocionRepuesto.repuesto", "repuesto")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("repuesto.idRepuesto"))))
			
				.add(Restrictions.eq("promocion.idPromocion", promocion.getIdPromocion()));
				
		List<Integer> listaIdsRepuestosNoAsignables = criteriaIdsRepuestosNoAsignables.list();
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class);
		criteria.setProjection(Projections.distinct(Projections
				.projectionList()
				.add(Projections.property("idRepuesto"), "idRepuesto")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("nombre"), "nombre")
				.add(Projections.property("codigo"), "codigo")
				.add(Projections.property("estado"), "estado")
				.add(Projections.property("unidadMedida"), "unidadMedida")
		));
		
		if (listaIdsRepuestosNoAsignables != null && listaIdsRepuestosNoAsignables.size() > 0) {
			criteria.add(Restrictions.not(Restrictions.in("idRepuesto", listaIdsRepuestosNoAsignables)));
		}
		
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		criteria.add(Restrictions.eq("estado", Constantes.ESTADO_ACTIVO));
		
		criteria.setFirstResult(inicio);
		criteria.setMaxResults(numeroResultadosPorPagina);
		
		if (!(columnaOrden == null)) {
			if (orden.toString().equals(Constantes.ORDEN_ASCENDENTE_PRIMEFACES)) {
				criteria.addOrder(Order.asc(columnaOrden.toString()));
			} else {
				criteria.addOrder(Order.desc(columnaOrden.toString()));
			}
		}
		criteria.setResultTransformer(Transformers.aliasToBean(Repuesto.class));
		return criteria.list();
	}

	@Override
	public Integer obtenerNumeroRepuestosAsignablesPorImagen(Repuesto repuesto, Imagen imagen) {
		
		Criteria criteriaIdsRepuestosNoAsignables = sessionFactory.getCurrentSession().createCriteria(ImagenRepuesto.class, "imagenRepuesto")
				.createAlias("imagenRepuesto.imagen", "imagen")
				.createAlias("imagenRepuesto.repuesto", "repuesto")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("repuesto.idRepuesto"))))
				
				.add(Restrictions.eq("imagen.idImagen", imagen.getIdImagen()))
				.add(Restrictions.not(Restrictions.eq("imagenRepuesto.estado", Constantes.ESTADO_ELIMINADO)));
				
		List<Integer> listaIdsRepuestosNoAsignables = criteriaIdsRepuestosNoAsignables.list();
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class)
				.setProjection(Projections.count("idRepuesto"));
		
		if (listaIdsRepuestosNoAsignables != null && listaIdsRepuestosNoAsignables.size() > 0) {
			criteria.add(Restrictions.not(Restrictions.in("idRepuesto", listaIdsRepuestosNoAsignables)));
		}
		
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		criteria.add(Restrictions.eq("estado", Constantes.ESTADO_ACTIVO));
		
		Number result = (Number) criteria.uniqueResult();
		
		return new Integer(result.intValue());
	}

	@Override
	public Integer obtenerNumeroRepuestosAsignablesPorPromocion(Repuesto repuesto, Promocion promocion) {
		Criteria criteriaIdsRepuestosNoAsignables = sessionFactory.getCurrentSession().createCriteria(PromocionRepuesto.class, "promocionRepuesto")
				.createAlias("promocionRepuesto.promocion", "promocion")
				.createAlias("promocionRepuesto.repuesto", "repuesto")
				.setProjection(Projections.projectionList().add(Projections.distinct(Projections.property("repuesto.idRepuesto"))))
				
				.add(Restrictions.eq("promocion.idPromocion", promocion.getIdPromocion()));
				//.add(Restrictions.not(Restrictions.eq("promocionRepuesto.estado", Constantes.ESTADO_ELIMINADO)));
				
		List<Integer> listaIdsRepuestosNoAsignables = criteriaIdsRepuestosNoAsignables.list();
		
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Repuesto.class)
				.setProjection(Projections.count("idRepuesto"));
		
		if (listaIdsRepuestosNoAsignables != null && listaIdsRepuestosNoAsignables.size() > 0) {
			criteria.add(Restrictions.not(Restrictions.in("idRepuesto", listaIdsRepuestosNoAsignables)));
		}
		
		if (repuesto.getCodigo() != null && !repuesto.getCodigo().equals("")) {
			criteria.add(Restrictions.like("codigo","%"+repuesto.getCodigo()+"%").ignoreCase());
		}

		if (repuesto.getNombre() != null && !repuesto.getNombre().equals("")) {
			criteria.add(Restrictions.like("nombre","%"+repuesto.getNombre()+"%").ignoreCase());
		}

		criteria.add(Restrictions.eq("estado", Constantes.ESTADO_ACTIVO));
		
		Number result = (Number) criteria.uniqueResult();
		
		return new Integer(result.intValue());
	}
	
	
}
